package com.xli.mybatis.interceptor;

import com.xli.mybatis.anno.EncryptField;
import com.xli.mybatis.support.Encrypt;
import com.xli.mybatis.support.EncryptFactory;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;

@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class DecryptInterceptor implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object results = invocation.proceed();

        if (results instanceof List) {
            if (((List<?>) results).isEmpty()) {
                return results;
            }
            for (Object result : (List<?>) results) {
                Class<?> clazz = result.getClass();
                for (Field field : clazz.getDeclaredFields()) {
                    if (field.isAnnotationPresent(EncryptField.class)) {
                        //如果有加密注解
                        field.setAccessible(true);
                        try {
                            String value = (String) field.get(result);
                            if (value != null) {
                                // 密文
                                EncryptField annotation = field.getAnnotation(EncryptField.class);
                                if (annotation != null) {
                                    Encrypt service = EncryptFactory.getEncryptionService(annotation.type());
                                    field.set(result, service.decrypt(value, annotation.key()));
                                }
                            }
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException("解密字段失败", e);
                        }
                    }
                }
            }
        }

        return results;
    }
}
